<template>
	<transition
		name="wly-drawer-fade"
		@after-enter="afterEnter"
		@after-leave="afterLeave"
	>
		<div class="wly-drawer__wrapper" tabindex="-1" v-show="visible">
			<div
				class="wly-drawer__container"
				:class="visible && 'wly-drawer__open'"
				@click.self="handleWrapperClick"
				role="document"
				tabindex="-1"
			>
				<div
					aria-modal="true"
					aria-labelledby="wly-drawer__title"
					:aria-label="title"
					class="wly-drawer"
					:class="[direction, customClass]"
					:style="
						isHorizontal ? `width: ${drawerSize}` : `height: ${drawerSize}`
					"
					ref="drawer"
					role="dialog"
					tabindex="-1"
				>
					<header
						class="wly-drawer__header"
						id="wly-drawer__title"
						v-if="withHeader"
					>
						<slot name="title">
							<span role="heading" :title="title">{{ title }}</span>
						</slot>
						<button
							:aria-label="`close ${title || 'drawer'}`"
							class="wly-drawer__close-btn"
							type="button"
							v-if="showClose"
							@click="closeDrawer"
						>
							<i class="wly-dialog__close wly-icon wly-icon-close"></i>
						</button>
					</header>
					<section class="wly-drawer__body" v-if="rendered">
						<slot></slot>
					</section>
				</div>
			</div>
		</div>
	</transition>
</template>

<script>
import './wly.css'
export default {
	name: 'wlyDrawer',
	props: {
		appendToBody: {
			type: Boolean,
			default: false
		},
		beforeClose: { type: Function },
		customClass: {
			type: String,
			default: ''
		},
		closeOnPressEscape: {
			type: Boolean,
			default: true
		},
		destroyOnClose: {
			type: Boolean,
			default: false
		},
		modal: {
			type: Boolean,
			default: true
		},
		direction: {
			type: String,
			default: 'rtl',
			validator(val) {
				return ['ltr', 'rtl', 'ttb', 'btt'].indexOf(val) !== -1
			}
		},
		modalAppendToBody: {
			type: Boolean,
			default: true
		},
		showClose: {
			type: Boolean,
			default: true
		},
		size: {
			type: [Number, String],
			default: '30%'
		},
		title: {
			type: String,
			default: ''
		},
		visible: { type: Boolean },
		wrapperClosable: {
			type: Boolean,
			default: true
		},
		withHeader: {
			type: Boolean,
			default: true
		}
	},
	computed: {
		isHorizontal() {
			return this.direction === 'rtl' || this.direction === 'ltr'
		},
		drawerSize() {
			return typeof this.size === 'number' ? `${this.size}px` : this.size
		}
	},
	data() {
		return {
			closed: false,
			rendered: false,
			prevActiveElement: null
		}
	},
	watch: {
		visible(val) {
			if (val) {
				this.closed = false
				this.$emit('open')
				if (this.appendToBody) {
					document.body.appendChild(this.$el)
				}
				this.prevActiveElement = document.activeElement
			} else {
				if (!this.closed) {
					this.$emit('close')
					if (this.destroyOnClose === true) {
						this.rendered = false
					}
				}
				this.$nextTick(() => {
					if (this.prevActiveElement) {
						this.prevActiveElement.focus()
					}
				})
			}
		}
	},
	methods: {
		afterEnter() {
			this.$emit('opened')
		},
		afterLeave() {
			this.$emit('closed')
		},
		hide(cancel) {
			if (cancel !== false) {
				this.$emit('update:visible', false)
				this.$emit('close')
				if (this.destroyOnClose === true) {
					this.rendered = false
				}
				this.closed = true
			}
		},
		handleWrapperClick() {
			if (this.wrapperClosable) {
				this.closeDrawer()
			}
		},
		closeDrawer() {
			if (typeof this.beforeClose === 'function') {
				this.beforeClose(this.hide)
			} else {
				this.hide()
			}
		},
		handleClose() {
			// This method here will be called by PopupManger, when the `closeOnPressEscape` was set to true
			// pressing `ESC` will call this method, and also close the drawer.
			// This method also calls `beforeClose` if there was one.
			this.closeDrawer()
		}
	},
	mounted() {
		if (this.visible) {
			this.rendered = true
			this.open()
			if (this.appendToBody) {
				document.body.appendChild(this.$el)
			}
		}
	},
	destroyed() {
		// if appendToBody is true, remove DOM node after destroy
		if (this.appendToBody && this.$el && this.$el.parentNode) {
			this.$el.parentNode.removeChild(this.$el)
		}
	}
}
</script>

<style>
.wly-drawer {
	position: absolute;
	box-sizing: border-box;
	background-color: #fff;
	display: flex;
	flex-direction: column;
	box-shadow: 0 8px 10px -5px rgb(0 0 0 / 20%), 0 16px 24px 2px rgb(0 0 0 / 14%),
		0 6px 30px 5px rgb(0 0 0 / 12%);
	overflow: hidden;
	outline: 0;
}
.wly-drawer__wrapper {
	position: fixed;
	top: 0;
	right: 0;
	bottom: 0;
	left: 0;
	overflow: hidden;
	margin: 0;
}
.wly-drawer__container {
	position: relative;
	left: 0;
	right: 0;
	top: calc(var(--status-bar-height) + 80rpx);
	bottom: 0;
	height: 100%;
	width: 100%;
}
.wly-drawer__open .wly-drawer.rtl {
	animation: rtl-drawer-in 0.3s 1ms;
}
.wly-drawer.rtl {
	right: 0;
}
.wly-drawer.ltr,
.wly-drawer.rtl {
	height: 100%;
	top: 0;
	bottom: 0;
}
.wly-drawer__header {
	align-items: center;
	color: #72767b;
	display: flex;
	margin-bottom: 32px;
	padding: 20px 20px 0;
}
.wly-drawer__header > :first-child {
	flex: 1;
}
.wly-drawer__header {
	align-items: center;
	color: #72767b;
	display: flex;
	margin-bottom: 32px;
	padding: 20px 20px 0;
}
.wly-drawer__close-btn {
	border: none;
	cursor: pointer;
	font-size: 20px;
	color: inherit;
	background-color: transparent;
}
.wly-drawer__body {
	padding: 20px;
}
.wly-drawer__body {
	flex: 1;
	overflow: auto;
}
.wly-drawer__body > * {
	box-sizing: border-box;
}
</style>
